import numpy as np
import pandas as pd

# 加载数据集
def load_data(filename):
    data = pd.read_csv(filename, header=None)
    return data

# 计算欧氏距离
def euclidean_distance(row1, row2):
    return np.sqrt(np.sum((row1 - row2) ** 2))

# 获取邻居的索引
def get_neighbors(train, test_row, num_neighbors):
    distances = [euclidean_distance(test_row, train_row) for train_row in train]
    sorted_indices = np.argsort(distances)[:num_neighbors]
    return sorted_indices

# 预测分类
def predict_classification(train, test_row, train_labels, num_neighbors):
    neighbors_indices = get_neighbors(train, test_row, num_neighbors)
    neighbors_labels = [train_labels[i] for i in neighbors_indices]
    prediction = max(set(neighbors_labels), key=neighbors_labels.count)
    return prediction

# 准确度
def accuracy_metric(actual, predicted):
    correct_count = sum(a == p for a, p in zip(actual, predicted))
    return correct_count / len(actual)

# KNN算法
def knn(train_data, test_data, train_labels, test_labels, num_neighbors):
    predictions = [predict_classification(train_data, test_row, train_labels, num_neighbors) for test_row in test_data]
    accuracy = accuracy_metric(test_labels, predictions)
    return predictions, accuracy

# 主函数
def main():
    # 加载数据
    data = load_data('./iris/iris.data')
    np.random.seed(7)  # 为了可重复性
    shuffled_indices = np.random.permutation(len(data))
    train_indices = shuffled_indices[:int(len(data) * 0.8)]
    test_indices = shuffled_indices[int(len(data) * 0.8):]
    
    # 划分训练集和测试集
    train_data = data.iloc[train_indices, :-1].values
    test_data = data.iloc[test_indices, :-1].values
    train_labels = data.iloc[train_indices, -1].values
    test_labels = data.iloc[test_indices, -1].values
    
    # KNN参数
    num_neighbors = 5
    
    # 执行KNN
    predictions, accuracy = knn(train_data, test_data, train_labels, test_labels, num_neighbors)
    
    # 打印结果
    print("Predictions:", predictions)
    print("Accuracy:", accuracy)

if __name__ == "__main__":
    main()